﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using DDD;
using Xunit;

namespace DokiDokiTest {
    public class TestWorld {
        [Fact]
        public void Test_New1 () {
            var wld = new World ();

            Assert.Equal (false, wld.IsFreezed);
            Assert.Equal (0, wld.ChildCount);
        }

        [Fact]
        public void Test_ActiveCamera () {
            var wld = new World ();
            var nod1 = new Node ();
            var nod2 = new Node ();
            var cam1 = new Camera ();
            var cam2 = new Camera ();
            nod1.Attach (cam1);
            nod2.Attach (cam2);
            wld.AddChild (nod1);
            wld.AddChild (nod2);

            wld.SetActiveCamera (nod1);
            Assert.Equal (nod1, wld.ActiveCamera);

            wld.SetActiveCamera (nod2);
            Assert.Equal (nod2, wld.ActiveCamera);

            wld.SetActiveCamera (null);
            Assert.Equal (null, wld.ActiveCamera);
        }

        [Fact]
        public void Test_Freeze () {
            var wld = new World ();
            wld.Freeze ();

            Assert.Equal (true, wld.IsFreezed);
        }

        [Fact]
        public void Test_DeFreeze () {
            var wld = new World ();
            wld.Freeze ();
            wld.DeFreeze ();

            Assert.Equal (false, wld.IsFreezed);
        }

        /// <summary>
        /// 列挙子のテスト
        /// </summary>
        /// <remarks>
        /// (注意)Freezeする前と後で内部的な処理が違うので両方テストすること。
        /// </remarks>
        [Fact]
        public void Test_IEnumerator () {
            var wld = new World ();
            var nod1 = new Node ();
            var nod2 = new Node ();
            wld.AddChild (nod1);
            wld.AddChild (nod2);
            wld.UserID = 1;
            nod1.UserID = 2;
            nod2.UserID = 4;

            Assert.Equal (7, wld.Sum (node => node.UserID));

            wld.Freeze ();

            Assert.Equal (7, wld.Sum (node => node.UserID));
        }

        [Fact]
        public void Test_Update () {
            var wld = new World ();
            var nod1 = new Node ();
            var nod2 = new Node ();
            var cmp1 = new MyTestComponent();
            var cmp2 = new MyTestComponent();
            wld.AddChild (nod1);
            wld.AddChild (nod2);
            nod1.Attach (cmp1);
            nod2.Attach (cmp2);

            wld.Update (0);

            Assert.Equal (1, cmp1.Value);
            Assert.Equal (1, cmp2.Value);
        }

        /// <summary>
        /// 参照のテスト
        /// </summary>
        /// <remarks>
        /// (*1) ユニークなのはnod1,nod2の2つだが
        /// ActiveCameraの分１つ重複して3つ帰ってくる
        /// </remarks>
        [Fact]
        public void Test_References () {
            var wld = new World ();
            var nod1 = new Node ();
            var nod2 = new Node ();
            wld.AddChild (nod1);
            wld.AddChild (nod2);

            var cam = new Camera ();
            nod2.Attach (cam);
            wld.SetActiveCamera (nod2);

            var objs = wld.References;        // (*1)
            var uniqObjs = objs.Distinct ();  // (*1)

            Assert.Equal (3, objs.Count());     
            Assert.Equal (2, uniqObjs.Count ());
            Assert.Equal (true, objs.All (x => x != null));

        }

        [Fact]
        public void Test_Find () {
            var wld = new World ();
            var nod1 = new Node ();
            var nod2 = new Node ();
            wld.AddChild (nod1);
            wld.AddChild (nod2);

            var cam = new Camera ();
            nod2.Attach (cam);
            wld.SetActiveCamera (nod2);

            nod1.UserID = 101;
            nod2.UserID = 102;
            cam.UserID = 103;
            wld.UserID = 104;

            Assert.Equal (nod1, wld.Find (101));
            Assert.Equal (nod2, wld.Find (102));
            Assert.Equal (cam, wld.Find (103));
            //Assert.Equal (wld, wld.Find (104));   // なぜかNullReferenceException
        }


    }
}
